# -*- coding: utf-8 -*-
# Created by shu2015626 on 2019-7-3
"""
在后台通过配置该任务的参数（需要执行的python文件，和类）实现动态配置任务的无敌
"""
import re
import logging
import paramiko
from celery import shared_task

from apps.CeleryTaskBase import CeleryTaskBase
from ..models import HostsInfo

logger = logging.getLogger("tasks")


# @shared_task(bind=True, name="remote.paramiko_remote_task",  base=CeleryTaskBase,
#              max_retries=3, default_retry_delay=10 * 60,
#              retry_kwargs={'max_retries': 3, 'countdown': 10 * 60})
# def paramiko_remote_task(self, cmd, ip, port=22, username=None, password=None):
#     """
#     使用paramiko执行远程主机上的任务。
#     不过这样密码会被明文存储。因此采用下面的方式
#     :param self:
#     :param cmd:
#     :param ip:
#     :param port:
#     :param username:
#     :param password:
#     :return:
#     """
#     ssh = paramiko.SSHClient()
#     try:
#         res = {}
#         ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#         ssh.connect(ip, port, username, password)  # timeout=5)
#         stdin, stdout, stderr = ssh.exec_command(cmd)
#         # print(stdout.read())
#         # print('%s OK\n' % (host_ip))
#         res['result'] = stdout.read()
#         res['cmd'] = cmd
#         res['remote_ip'] = ip
#         res['remote_port'] = port
#         res['remote_user'] = username
#         res['hostname'] = self.request.hostname
#         res['task_name'] = self.request.task
#         res['task_id'] = self.request.id
#         return res
#     finally:
#         try:
#             ssh.close()
#         except Exception as e:
#             ssh = None

@shared_task(bind=True, name="remote.paramiko_remote_task",  base=CeleryTaskBase,
             max_retries=3, default_retry_delay=10 * 60,
             retry_kwargs={'max_retries': 3, 'countdown': 10 * 60})
def paramiko_remote_task(self, cmd: str, host_flag: str):
    """
    执行远程主机任务。
    需要先在后台配置：要登录的主机信息。
    这里只需要传入主机标识即可
    :param self: task任务本身
    :param cmd: 需要执行的任务命令：注意必须是全路径
    :param host_flag: 主机标识
    :return:
    """
    ssh = paramiko.SSHClient()
    try:
        res = {}
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        obj_hosts = HostsInfo.objects.filter(host_flag=host_flag, is_deleted__exact=0)
        if not obj_hosts:
            raise Exception(f"不存在主机标识为：{host_flag}并且有效的主机，请检查输入的主机标识")
        obj_host = obj_hosts[0]
        ip = obj_host.ip
        port = obj_host.port
        username = obj_host.username
        password = obj_host.get_password()
        ssh.connect(ip, port, username, password)  # timeout=5)
        stdin, stdout, stderr = ssh.exec_command(cmd)

        # 获取执行的文件名称
        operate_file = re.split(r"[/\\]", cmd.strip())[-1]
        if operate_file and "." in operate_file:
            self.request.operate_file = operate_file

        try:
            out = stdout.read().decode('utf-8')
        except UnicodeDecodeError as e:
            try:
                out = stdout.read().decode('gb18030')
            except UnicodeDecodeError as e:
                out = None

        # print(stdout.read())
        # print('%s OK\n' % (host_ip))
        res['result'] = out
        res['cmd'] = cmd
        res['host_flag'] = host_flag
        res['remote_ip'] = ip
        res['remote_port'] = port
        res['remote_user'] = username
        res['hostname'] = self.request.hostname
        res['task_name'] = self.request.task
        res['task_id'] = self.request.id
        return res
    finally:
        try:
            ssh.close()
        except Exception as e:
            ssh = None
